#include "ModBus/ModBusCollectManager.h"
#include "ModBus/ModBusProcess.h"
#include "Log/Logger.h"
#include <cstring>

ModBusCollectManager::ModBusCollectManager(/* args */) : 
    mb(nullptr)
{
    mQuit.store(false);
}

ModBusCollectManager::~ModBusCollectManager()
{
    mQuit.store(true);
    if (mb)
    {
        modbus_free(mb);
    }
    if(threadProcess.joinable())
    {
        threadProcess.join();
    }
}

void ModBusCollectManager::init(const modbusConnectInfo &conInfo)
{
    _modbusConInfo = conInfo;
}

void ModBusCollectManager::start()
{
    processPtr = new ModBusProcess();
    processPtr->init();
    threadProcess = std::thread(&ModBusProcess::start, processPtr);
    
    while (!mQuit.load())
    {
        if (!connect())
        {
            Logger::getInstance().error("connect fail, waiting for the next connection. baudrate is :" + std::to_string(_modbusConInfo.nBaudRate));
            std::this_thread::sleep_for(std::chrono::milliseconds(5000));
            continue;
        }
        collect();
    }
}

bool ModBusCollectManager::connect(bool bReconnect, int nReTimes)
{
    // 创建Modbus RTU连接
    mb = modbus_new_rtu(_modbusConInfo.strDevice.c_str(),
                        _modbusConInfo.nBaudRate,
                        _modbusConInfo.cParity,
                        _modbusConInfo.nDataBit,
                        _modbusConInfo.nStopBit);
    if (mb == nullptr)
    {
        Logger::getInstance().error("Unable to create the libmodbus context");
        return false;
    }

    // 设置Modbus通信超时
    struct timeval timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    modbus_set_response_timeout(mb, timeout.tv_sec, timeout.tv_usec);

    modbus_set_slave(mb, 1);

    // 连接Modbus
    if (modbus_connect(mb) == -1)
    {
        Logger::getInstance().error("Unable to connect to the Modbus server");
        modbus_free(mb);
        mb = nullptr;
        return false;
    }
    return true;
}

void ModBusCollectManager::collect()
{
    while (!mQuit.load())
    {
        modbus_set_slave(mb, 1);
        // 读取保持寄存器（功能代码0x03）
        uint16_t tab_reg[32];                               // 存储寄存器数据
        int rc = modbus_read_registers(mb, 100, 3, tab_reg); // 从地址0读取10个寄存器
        if (rc == -1) 
        {
            Logger::getInstance().error("Modbus read error");
            modbus_free(mb);
            mb = nullptr;
            return;
        }

        MODBUS::CollectData cData;
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);

        // 打印读取到的寄存器值
        Logger::getInstance().info("Read registers:");
        std::memcpy(cData.rawData, tab_reg, 3);
        cData.dTimestamp = ts.tv_nsec;
        processPtr->update(cData);

        // for (int i = 0; i < 3; i++)
        // {
        //     Logger::getInstance().info("Register " + std::to_string(i) + ": " + std::to_string(tab_reg[i]));
        //     cData.nSerinal = i + 1;
        //     cData.dData = tab_reg[i];
        //     cData.dTimestamp = ts.tv_nsec; //纳秒时间戳
        //     processPtr->update(cData);
        // }
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}

void ModBusCollectManager::stop()
{
    if(processPtr)
        processPtr->stop();
    mQuit.store(true);
}
